VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "ApiPrintJob"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

' ##MODULE_DESCRIPTION This class provides the properties _
for a getting information about a job in a printer queue.

' ##ENUMERATION_DESCRIPTION PrintJobStatuses are the various different statuses that it is possible for _
a job on a print queue to be in.
Public Enum PrintJobStatuses
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_PAUSED The print job has been paused during printing
    JOB_STATUS_PAUSED = &H1
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_ERROR The print job is stalled by an error
    JOB_STATUS_ERROR = &H2
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_DELETING The print job is being deleted from the queue
    JOB_STATUS_DELETING = &H4
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_SPOOLING The print job is being added to the spooler queue
    JOB_STATUS_SPOOLING = &H8
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_PRINTING The print job is in the midst of being printed
    JOB_STATUS_PRINTING = &H10
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_OFFLINE The print job is stalled because the printer is off line
    JOB_STATUS_OFFLINE = &H20
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_PAPEROUT The print job is stalled because the printer has run out of paper
    JOB_STATUS_PAPEROUT = &H40
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_PRINTER The print job is waiting on the printer
    JOB_STATUS_PRINTER = &H80
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_DELETED The print job has been deleted
    JOB_STATUS_DELETED = &H100
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_BLOCKED_DEVICEQUEUE The device queue is blocked so the print job is also blocked
    JOB_STATUS_BLOCKED_DEVICEQUEUE = &H200
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_USER_INTERVENTION The queued job is paused by user intervention
    JOB_STATUS_USER_INTERVENTION = &H400
    ' ##ENUMERATION_MEMBER_DESCRIPTION JOB_STATUS_RESTART The queued print job is restarting after being paused
    JOB_STATUS_RESTART = &H800
End Enum

Private Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type

Private Type JOB_INFO_1
    JobId As Long
    lpPrinterName As String
    lpMachinename As String
    lpUserName As String
    lpDocumentName As String
    lpDataType As String
    lpStatus As String
    Status As PrintJobStatuses
    Priority As Long
    Position As Long
    TotalPages As Long
    PagesPrinted As Long
    Submitted As SYSTEMTIME
End Type

Private Type JOB_INFO_2
    JobId As Long
    lpPrinterName As String
    lpMachinename As String
    lpUserName As String
    lpDocumentName As String
    lpNotifyName As String
    lpDataType As String
    lpPrintProcessor As String
    lpParameters As String
    lpDriverName As String
    lpDevmode As Long 'Pointer to DevMode
    lpStatus As String
    lpSecurityDescriptor As Long 'Pointer to SECURITY_DESCRIPTOR
    Status As PrintJobStatuses
    Priority As Long
    Position As Long
    StartTime As Long
    UntilTime As Long
    TotalPages As Long
    JobSize As Long
    Submitted As SYSTEMTIME
    time As Long
    PagesPrinted As Long
End Type

'\\ Included in WINNT4 and beyond
Private Type JOB_INFO_3
    JobId As Long
    NextJobId As Long
    Reserved As Long 'must be set to zero
End Type

Private Declare Function GetJob Lib "winspool.drv" Alias "GetJobA" _
                          (ByVal hPrinter As Long, _
                           ByVal JobId As Long, _
                           ByVal Level As Long, _
                           buffer As Long, _
                           ByVal pbSize As Long, _
                           pbSizeNeeded As Long) As Long
                           

'\\ Private member variables
Private mJobId As Long 'Unique id of this job
Private mhPrinter As Long 'Printer this job is on...

Private mJOB_INFO_1 As JOB_INFO_1
Private mJOB_INFO_2 As JOB_INFO_2
Private mJOB_INFO_3 As JOB_INFO_3

'\\ Private variable to prevent unneccessary calls to the dll...
Private mLastApiCall(1 To 3) As Date

Public Property Get DataType() As String

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    DataType = mJOB_INFO_1.lpDataType
End If

End Property

Public Property Get DocumentName() As String

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    DocumentName = mJOB_INFO_1.lpDocumentName
End If

End Property


Friend Property Let JobId(ByVal newJobId As Long)

    mJobId = newJobId
    
End Property

Public Property Get JobId() As Long

    JobId = mJobId
    
End Property

Public Property Get MachineName() As String

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    MachineName = mJOB_INFO_1.lpMachinename
End If

End Property

Public Property Get PagesPrinted() As Long

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    PagesPrinted = mJOB_INFO_1.PagesPrinted
End If

End Property

Public Property Get Position() As Long

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    Position = mJOB_INFO_1.Position
End If

End Property

Friend Property Let PrinterHandle(ByVal newhPrinter As Long)

    mhPrinter = newhPrinter
    
End Property
Public Property Get PrinterName() As String

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    PrinterName = mJOB_INFO_1.lpPrinterName
End If

End Property

Public Property Get Priority() As Long

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    Priority = mJOB_INFO_1.Priority
End If

End Property

Private Sub RefreshJobInfo(ByVal index As Integer)

Dim lRet As Long
Dim SizeNeeded As Long

Dim buffer() As Long

'\\ Prevent unneccesary call to the API
If DateDiff("s", mLastApiCall(index), Now) > 1 Then
    mLastApiCall(index) = Now
        
    ReDim Preserve buffer(0 To 1) As Long
    lRet = GetJob(mhPrinter, mJobId, index, buffer(0), UBound(buffer), SizeNeeded)
    
    If SizeNeeded > 0 Then
        ReDim Preserve buffer(0 To (SizeNeeded / 4) + 3) As Long
        lRet = GetJob(mhPrinter, mJobId, index, buffer(0), UBound(buffer) * 4, SizeNeeded)
        
        If index < 1 Or index > 3 Then
            Debug.Print "Error in call to ApiPrintJob:RefreshJobInfo - invalid index"
        Else
            Select Case index
            Case 1
                With mJOB_INFO_1
                    .JobId = buffer(0)
                    .lpPrinterName = StringFromPointer(buffer(1), 1024)
                    .lpMachinename = StringFromPointer(buffer(2), 1024)
                    .lpUserName = StringFromPointer(buffer(3), 1024)
                    .lpDocumentName = StringFromPointer(buffer(4), 1024)
                    .lpDataType = StringFromPointer(buffer(5), 1024)
                    .lpStatus = StringFromPointer(buffer(6), 1024)
                    .Status = buffer(7)
                    .Priority = buffer(8)
                    .Position = buffer(9)
                    .TotalPages = buffer(10)
                    .PagesPrinted = buffer(11)
                    'Submitted is also here...
                    With .Submitted
                        .wYear = APIDispenser.LoWord(buffer(12))
                        .wMonth = APIDispenser.HiWord(buffer(12))
                        .wDayOfWeek = APIDispenser.LoWord(buffer(13))
                        .wDay = APIDispenser.HiWord(buffer(13))
                        .wHour = APIDispenser.LoWord(buffer(14))
                        .wMinute = APIDispenser.HiWord(buffer(14))
                        .wSecond = APIDispenser.LoWord(buffer(15))
                        .wMilliseconds = APIDispenser.HiWord(buffer(15))
                    End With
                End With
            Case 2
                With mJOB_INFO_2
                    .JobId = buffer(0)
                    .lpPrinterName = StringFromPointer(buffer(1), 1024)
                    .lpMachinename = StringFromPointer(buffer(2), 1024)
                    .lpUserName = StringFromPointer(buffer(3), 1024)
                    .lpDocumentName = StringFromPointer(buffer(4), 1024)
                    .lpNotifyName = StringFromPointer(buffer(5), 1024)
                    .lpDataType = StringFromPointer(buffer(6), 1024)
                    .lpPrintProcessor = StringFromPointer(buffer(7), 1024)
                    .lpParameters = StringFromPointer(buffer(8), 1024)
                    .lpDriverName = StringFromPointer(buffer(9), 1024)
                    .lpDevmode = buffer(10) 'To do: Replace with ApiDevMode class when available
                    .lpStatus = StringFromPointer(buffer(11), 1024)
                    .lpSecurityDescriptor = buffer(12) 'To do: Replace...
                    .Status = buffer(13)
                    .Priority = buffer(14)
                    .Position = buffer(15)
                    .StartTime = buffer(16)
                    .UntilTime = buffer(17)
                    .TotalPages = buffer(18)
                    .JobSize = buffer(19)
                    'Submitted is here....
                    '4 long values, packed with 8 integers
                    With .Submitted
                        .wYear = APIDispenser.LoWord(buffer(20))
                        .wMonth = APIDispenser.HiWord(buffer(20))
                        .wDayOfWeek = APIDispenser.LoWord(buffer(21))
                        .wDay = APIDispenser.HiWord(buffer(21))
                        .wHour = APIDispenser.LoWord(buffer(22))
                        .wMinute = APIDispenser.HiWord(buffer(22))
                        .wSecond = APIDispenser.LoWord(buffer(23))
                        .wMilliseconds = APIDispenser.HiWord(buffer(23))
                    End With
                    .time = buffer(24)
                    .PagesPrinted = buffer(25)
                End With
            Case 3
                With mJOB_INFO_3
                    .JobId = buffer(0)
                    .NextJobId = buffer(1)
                    .Reserved = buffer(2)
                End With
            End Select
        End If
    End If
End If

End Sub

Public Property Get Status() As PrintJobStatuses

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    Status = mJOB_INFO_1.Status
End If

End Property


Public Property Get Submitted() As APISystemTime

Dim oSystemTime As APISystemTime

Call RefreshJobInfo(1)

Set oSystemTime = New APISystemTime
oSystemTime.CreateFromPointer (VarPtr(mJOB_INFO_1.Submitted))

Set Submitted = oSystemTime

End Property

Public Property Get TotalPages() As Long

If mhPrinter <> 0 And mJobId <> 0 Then
    Call RefreshJobInfo(1)
    TotalPages = mJOB_INFO_1.TotalPages
End If

End Property

Public Property Get StartTime() As Long

Call RefreshJobInfo(2)
StartTime = mJOB_INFO_2.StartTime

End Property

Public Property Get UntilTime() As Long

Call RefreshJobInfo(2)
UntilTime = mJOB_INFO_2.UntilTime

End Property


Public Property Get Username() As String

    Call RefreshJobInfo(1)
    Username = mJOB_INFO_1.lpUserName

End Property


